﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nova.Parsing.GoldParser.Semantic;
using Nova.Parsing.Tokens;

namespace Nova.Parsing.Constructs
{
    public sealed class CaseBlockSetConstruction : NovaConstruct, IEnumerable<CaseBlockConstruct>
    {
        private CaseBlockConstruct m_CurrentBlock;
        private CaseBlockSetConstruction m_NextBlock;

        [Rule(@"<Case-Blocks> ::= <Case-Blocks> <Case-Block>")]
        [Rule(@"<Case-Blocks> ::= ")]
        public CaseBlockSetConstruction(CaseBlockSetConstruction caseBlockSet, CaseBlockConstruct caseBlock)
        {
            m_CurrentBlock = caseBlock;
            m_NextBlock = caseBlockSet;
        }

        public CaseBlockConstruct CurrentCaseBlock
        {
            get { return m_CurrentBlock; }
        }

        public CaseBlockSetConstruction NextCaseBlockSet
        {
            get { return m_NextBlock; }
        }

        public IEnumerator<CaseBlockConstruct> GetEnumerator()
        {
            for (CaseBlockSetConstruction set = this; set != null; set = set.NextCaseBlockSet)
            {
                if (set.CurrentCaseBlock != null)
                {
                    yield return set.CurrentCaseBlock;
                }
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public sealed class CaseBlockConstruct : NovaConstruct
    {
        private CaseLabelSetConstruct m_Labels;
        private StatementSet m_Statements;

        [Rule(@"<Case-Block> ::= <Case-Labels> <Statements>")]
        public CaseBlockConstruct(CaseLabelSetConstruct labelSet, StatementSet statementSet)
        {
            m_Labels = labelSet;
            m_Statements = statementSet;
        }

        public CaseLabelSetConstruct Labels
        {
            get { return m_Labels; }
        }

        public StatementSet Statements
        {
            get { return m_Statements; }
        }
    }

    public sealed class CaseLabelSetConstruct : NovaConstruct, IEnumerable<CaseLabelConstruct>
    {
        private CaseLabelConstruct m_CurrentLabel;
        private CaseLabelSetConstruct m_NextLabelSet;

        [Rule(@"<Case-Labels> ::= <Case-Labels> <Case-Label>")]
        public CaseLabelSetConstruct(CaseLabelSetConstruct labelSet, CaseLabelConstruct label)
        {
            m_CurrentLabel = label;
            m_NextLabelSet = labelSet;
        }

        [Rule(@"<Case-Labels> ::= <Case-Label>")]
        public CaseLabelSetConstruct(CaseLabelConstruct label)
        {
            m_CurrentLabel = label;
            m_NextLabelSet = null;
        }

        public CaseLabelConstruct CurrentLabel
        {
            get { return m_CurrentLabel; }
        }

        public CaseLabelSetConstruct NextLabelSet
        {
            get { return m_NextLabelSet; }
        }

        public IEnumerator<CaseLabelConstruct> GetEnumerator()
        {
            for (CaseLabelSetConstruct set = this; set != null; set = set.NextLabelSet)
            {
                if (set.CurrentLabel != null)
                {
                    yield return set.CurrentLabel;
                }
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public sealed class CaseLabelConstruct : NovaConstruct
    {
        private bool m_IsDefault = false;
        private ExpressionConstruct m_CaseExpression;

        [Rule(@"<Case-Label> ::= case <Expression> ':'")]
        public CaseLabelConstruct(KeywordToken keyword, ExpressionConstruct expression, IgnoredToken iA)
        {
            m_IsDefault = false;
            m_CaseExpression = expression;
        }

        [Rule(@"<Case-Label> ::= default ':'")]
        public CaseLabelConstruct(KeywordToken keyword, IgnoredToken iA)
        {
            m_IsDefault = true;
            m_CaseExpression = null;
        }

        public bool isDefaultCase
        {
            get { return m_IsDefault; }
        }

        public ExpressionConstruct CaseExpression
        {
            get { return m_CaseExpression; }
        }
    }
}
